import { AmbientLight, CameraHelper, Group, PerspectiveCamera, PointLight, Scene, WebGLRenderer } from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js';

export default class ModelCommon {

    group: Group;
    scene: Scene;
    camera: PerspectiveCamera;
    renderer: WebGLRenderer;
    canvasWrap: HTMLDivElement;
    controls: OrbitControls | null = null;
    cameraHelper: CameraHelper | null = null;
    labelRenderer: CSS2DRenderer | null = null;
    lights: Array<AmbientLight | PointLight> = [];
    timer: number = 0;

    constructor(canvasOrId: string | HTMLDivElement = "webgl-output") {
        this.group = new Group();  // 分组，看做是div容器
        this.scene = new Scene();   // 场景容器，看做是最大的根div
        this.camera = new PerspectiveCamera();  // 摄像机，相当于人的眼睛
        this.renderer = new WebGLRenderer({ antialias: true, alpha: true });  // 渲染器
        if (typeof canvasOrId == 'string') {
            this.canvasWrap = document.getElementById(canvasOrId) as HTMLDivElement;   // 渲染器返回的canvas会插入到div容器中;
        } else {
            this.canvasWrap = canvasOrId;
        }
        this.init();  // 初始化
    }


    init() {
        this.scene.add(this.group);
        this.initCamera(this.scene, this.canvasWrap)
        this.initLight(this.scene)
        this.initRenderer();
        this.initControls();  // 鼠标控制视角，滚轮控制放大缩小
        this.timer && cancelAnimationFrame(this.timer) // 去除animationFrame
        this.render()  // 循环重绘canvas
        window.onresize = () => {
            if (this.camera) {
                this.camera.aspect = window.innerWidth / window.innerHeight;
                this.camera.updateProjectionMatrix();
            }
            if (this.renderer && this.canvasWrap) {
                let { width, height } = this.canvasWrap.getBoundingClientRect();
                this.renderer.setSize(width, height);
            }
            if (this.labelRenderer) {
                let { width, height } = this.canvasWrap.getBoundingClientRect();
                this.labelRenderer.setSize(width, height);
            }
        };
    }

    render = () => {
        if (this.renderer && this.scene && this.camera) {
            this.renderer.render(this.scene, this.camera) // 渲染
            this.timer = requestAnimationFrame(this.render) // 循环
        }
    }

    initCamera(scene: Scene, canvasWrap: HTMLDivElement) {
        let { width, height } = canvasWrap.getBoundingClientRect();
        this.camera.aspect = width / height;
        this.camera.layers.enableAll()
        this.camera.lookAt(scene.position);
        this.cameraHelper = new CameraHelper(this.camera);
        scene.add(this.camera)
    }

    initLight(scene: Scene) {
        let ambientLight = new AmbientLight('#fff', 1) // 创建环境光
        scene.add(ambientLight);
    }

    initRenderer() {
        if (this.canvasWrap) {
            // renderer.sortObjects = true;  // 设置模型可按顺序加载, 需要给每个对象设置renderOrder
            let { width, height } = this.canvasWrap.getBoundingClientRect();
            this.renderer.setSize(width, height);
            this.renderer.setClearColor("white");
        } else {
            throw new Error("未检测到canvas元素");
        }
        this.canvasWrap.appendChild(this.renderer.domElement);
    }

    // 初始化鼠标控制
    initControls() {
        this.renderer && this.initControl(this.renderer.domElement, this.camera) // 初始化鼠标控制
        this.labelRenderer && this.initControl(this.labelRenderer.domElement, this.camera);
    }

    initControl(domElement: HTMLElement, camera: PerspectiveCamera) {
        this.controls = new OrbitControls(camera, domElement)
        this.controls.rotateSpeed = 0.1;
        this.resetVisualAngle(this.controls)
    }

    // 初始化视角
    resetVisualAngle(controls: OrbitControls) {
        controls.target.set(1.5695694343449789, 12.77798919347029, 5.486396994976423)  // 初始视角
        this.camera.position.set(-31.15823345237321, 34.25050705321661, -30.717131216133055)
        this.camera.rotation.set(-2.6062579358044196, -0.6608850846726965, -2.792449620377006)
    }

    // 初始化html2D标签
    initLabelRenderer() {
        this.labelRenderer = new CSS2DRenderer();
        let { width, height } = this.canvasWrap.getBoundingClientRect();
        this.labelRenderer.setSize(width, height);
        this.labelRenderer.domElement.style.position = 'absolute';
        this.labelRenderer.domElement.style.top = '0px';
        document.body.appendChild(this.labelRenderer.domElement);
    }

    // 清空重置
    clear() {
        try {
            this.labelRenderer && document.body.removeChild(this.labelRenderer.domElement);
            this.renderer && document.body.removeChild(this.renderer.domElement);
            this.scene.clear();
            this.renderer.dispose();
            this.renderer.forceContextLoss();
            let gl = this.renderer.domElement.getContext("webgl");
            if(gl){
                gl.getExtension("WEBGL_lose_context")?.loseContext();
            }
        } catch (e) {
            console.log(e)
        }
        this.timer && cancelAnimationFrame(this.timer) // 去除animationFrame
        window.onresize = null;
    }
}
